#pragma once

#include <iostream>
#include <string>
#include <strings.h>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "log.hpp"

Log lg;

uint16_t defaultport = 8080;
std::string defaultip = "0.0.0.0";
const int size = 1024;

enum
{
    SOCK_ERR = 1,
    BIND_ERR,

};

class UdpServer
{
public:
    UdpServer(const uint16_t port = defaultport, const std::string &ip = defaultip)
        :port_(port), ip_(ip)
    {
    }

    void Init()
    {
        sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);
        std::cout <<sockfd_ <<std::endl;
        if (sockfd_ < 0)
        {
            lg(fatal, "socket create error, sockfd: %d", sockfd_);
            exit(SOCK_ERR);
        }
        lg(info, "socket create success,sockfd: %d", sockfd_);

        struct sockaddr_in local;
        bzero(&local, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(port_);
        //local.sin_addr.s_addr = inet_addr(ip_.c_str());
        local.sin_addr.s_addr = htonl(INADDR_ANY);

        // bind 绑定
        int n = bind(sockfd_, (const sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            lg(fatal, "bind error,errno: %d ,err_string: %s", errno, strerror(errno));
            exit(BIND_ERR);
        }
        lg(info, "bind success,errno: %d ,err_string: %s", errno, strerror(errno));
    }
    void Run()
    {
        is_running_ = true;
        char inbuffer[size];
        while (is_running_)
        {
            struct sockaddr_in cilent;
            socklen_t len = sizeof(cilent);
            ssize_t n = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, (struct sockaddr*)&cilent, &len);
            if (n < 0)
            {
                lg(warning, "recvfrom error, errno: %d, err string: %s", errno, strerror(errno));
                continue;
            }
            lg(info,"recvfrom success");

            inbuffer[n] = 0;
            std::string mes = inbuffer;
            std::string echo_string = "sever echo# " + mes;
            std::cout << echo_string << std::endl;
            sendto(sockfd_, echo_string.c_str(), echo_string.size(), 0, (const sockaddr *)&cilent, len);

        }
    }

    ~UdpServer()
    {
        if(sockfd_>0) close(sockfd_);
    }

private:
    int sockfd_;     // 网络文件描述符
    std::string ip_; // ip
    uint16_t port_;  //端口
    bool is_running_ = false;
};